package org.skydiveapplibrary.repository;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.skydiveapplibrary.data.Database;
import org.skydiveapplibrary.data.FreefallProfileType;
import org.skydiveapplibrary.data.SkydiveType;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class SkydiveTypeRepository
{
	// jump count query format
	private static final String JUMP_COUNT_QUERY_FORMAT =
		"select count(*) " +
		"from log_entry " +
		"where skydive_type = {0}";
	
	private Database database;
	
	public SkydiveTypeRepository(Context context)
	{
		database = new Database(context);
	}
	
	public List<SkydiveType> getAllSkydiveTypes()
	{
		return getSkydiveTypes(null);
	}
	
	public List<SkydiveType> getSkydiveTypes()
	{
		return getSkydiveTypes(Database.SKYDIVE_TYPE_ACTIVE + " = " + 1);
	}
	
	private List<SkydiveType> getSkydiveTypes(String where)
	{
		List<SkydiveType> skydiveTypes = new ArrayList<SkydiveType>();
		
		SQLiteDatabase db = database.getReadableDatabase();
		Cursor cursor = null;
		try
		{
			// perform query
			cursor = db.query(
					Database.SKYDIVE_TYPE_TABLE,
					Database.SKYDIVE_TYPE_ALL_COLUMNS,
					where,
					null, null, null,
					Database.SKYDIVE_TYPE_NAME);
			
			// iterate over results
			while (cursor.moveToNext())
			{
				// create skydive type
				SkydiveType skydiveType = createSkydiveType(cursor);
				skydiveTypes.add(skydiveType);
			}
		}
		finally
		{
			// close cursor
			if (cursor != null)
			{
				cursor.close();
			}
			// close database
			db.close();
		}
		
		return skydiveTypes;
	}
	
	public SkydiveType findSkydiveType(String name)
	{
		return getSkydiveType(Database.SKYDIVE_TYPE_NAME + " = ?", name);
	}
	
	public SkydiveType getSkydiveType(int id)
	{
		return getSkydiveType(Database.SKYDIVE_TYPE_ID + " = ?", String.valueOf(id));
	}
	
	public SkydiveType getFromUniqueId(String uniqueId)
	{
		return getSkydiveType(Database.SKYDIVE_TYPE_UNIQUE_ID + " = ?", uniqueId);
	}
	
	private SkydiveType getSkydiveType(String where, String... whereParams)
	{
		SkydiveType skydiveType = null;
		
		SQLiteDatabase db = database.getReadableDatabase();
		Cursor cursor = null;
		try
		{
			// perform query
			cursor = db.query(
					Database.SKYDIVE_TYPE_TABLE,
					Database.SKYDIVE_TYPE_ALL_COLUMNS,
					where,
					whereParams,
					null,
					null,
					null);
			
			if (cursor.moveToFirst())
			{
				skydiveType = createSkydiveType(cursor);
			}
		}
		finally
		{
			// close cursor
			if (cursor != null)
			{
				cursor.close();
			}
			// close database
			db.close();
		}
		
		return skydiveType;
	}
	
	public void addSkydiveType(SkydiveType skydiveType)
	{
		// set modified
		if (skydiveType.getLastModifiedUtc() == null)
		{
			skydiveType.setLastModifiedUtc(new Date(System.currentTimeMillis()));
		}
		
		//set uniqueId
		if (skydiveType.getUniqueId() == null || skydiveType.getUniqueId() == "")
		{
			skydiveType.setUniqueId(UUID.randomUUID().toString());
		}
		
		// get insert values
		ContentValues values = createContentValues(skydiveType);
		
		// do insert
		SQLiteDatabase db = database.getWritableDatabase();
		try
		{
			// do insert
			long id = db.insert(Database.SKYDIVE_TYPE_TABLE, null, values);
			skydiveType.setId((int)id);
		}
		finally
		{
			// close db
			db.close();
		}
	}
	
	public void updateSkydiveType(SkydiveType skydiveType)
	{
		updateSkydiveType(skydiveType, true);
	}
	
	public void updateSkydiveType(SkydiveType skydiveType, boolean updateLastModified)
	{
		// set modified
		if (updateLastModified)
		{
			skydiveType.setLastModifiedUtc(new Date(System.currentTimeMillis()));
		}
		
		// get update values
		ContentValues values = createContentValues(skydiveType);
		
		SQLiteDatabase db = database.getWritableDatabase();
		try
		{
			// do update
			db.update(Database.SKYDIVE_TYPE_TABLE,
					values,
					Database.SKYDIVE_TYPE_ID + " = " + skydiveType.getId(),
					null);
		}
		finally
		{
			// close db
			db.close();
		}
	}
	
	public void deleteSkydiveType(SkydiveType skydiveType)
	{
		SQLiteDatabase db = database.getWritableDatabase();
		try
		{
			// create update values
			ContentValues values = new ContentValues();
			values.put(Database.SKYDIVE_TYPE_ACTIVE, false);
					
			// deactivate
			db.update(
					Database.SKYDIVE_TYPE_TABLE,
					values,
					Database.SKYDIVE_TYPE_ID + " = " + skydiveType.getId(),
					null);					
		}
		finally
		{
			// close db
			db.close();
		}
	}
	
	private SkydiveType createSkydiveType(Cursor cursor)
	{
		SkydiveType skydiveType = new SkydiveType();
		
		skydiveType.setId(Database.getInteger(cursor, Database.SKYDIVE_TYPE_ID));
		skydiveType.setActive(Database.getBoolean(cursor, Database.SKYDIVE_TYPE_ACTIVE));
		skydiveType.setName(Database.getString(cursor, Database.SKYDIVE_TYPE_NAME));
		if (!Database.isNull(cursor, Database.SKYDIVE_TYPE_FREEFALL_PROFILE))
			skydiveType.setFreefallProfileType(FreefallProfileType.valueOf(Database.getString(cursor, Database.SKYDIVE_TYPE_FREEFALL_PROFILE)));
		skydiveType.setNotes(Database.getString(cursor, Database.SKYDIVE_TYPE_NOTES));
		skydiveType.setJumpCount(getJumpCount(skydiveType.getId(), database.getReadableDatabase()));
		skydiveType.setLastModifiedUtc(Database.getDateTime(cursor, Database.SKYDIVE_TYPE_LAST_MODIFIED_UTC));
		skydiveType.setUniqueId(Database.getString(cursor, Database.SKYDIVE_TYPE_UNIQUE_ID));
		
		return skydiveType;
	}
	
	private ContentValues createContentValues(SkydiveType skydiveType)
	{
		ContentValues values = new ContentValues();
		
		values.put(Database.SKYDIVE_TYPE_ACTIVE, skydiveType.isActive());
		values.put(Database.SKYDIVE_TYPE_NAME, skydiveType.getName());
		if (skydiveType.getFreefallProfileType() != null)
			values.put(Database.SKYDIVE_TYPE_FREEFALL_PROFILE, skydiveType.getFreefallProfileType().toString());
		values.put(Database.SKYDIVE_TYPE_NOTES, skydiveType.getNotes());
		values.put(Database.SKYDIVE_TYPE_LAST_MODIFIED_UTC, Database.dateTimeToString(skydiveType.getLastModifiedUtc()));
		values.put(Database.SKYDIVE_TYPE_UNIQUE_ID, skydiveType.getUniqueId());
		
		return values;
	}
	
	private int getJumpCount(int skydivetypeId, SQLiteDatabase db)
	{
		// construct query
		String query = MessageFormat.format(JUMP_COUNT_QUERY_FORMAT, skydivetypeId);
		// result
		int result = 0;
		
		// execute query
		Cursor cursor = null;
		try
		{
			cursor = db.rawQuery(query, null);
			
			// get results
			if (cursor.moveToFirst())
			{
				result = cursor.getInt(0);
			}
		}
		finally
		{
			// close cursor
			if (cursor != null)
			{
				cursor.close();
			}
		}
		
		return result;
	}
	
	public boolean exists(String where, String... whereParams)
	{
		SQLiteDatabase db = database.getReadableDatabase();
		Cursor cursor = null;
		try
		{
			// perform query
			cursor = db.query(
					Database.SKYDIVE_TYPE_TABLE,
					Database.SKYDIVE_TYPE_ALL_COLUMNS,
					where + " = ?",
					whereParams,
					null,
					null,
					null);
			
			return cursor.getCount() > 0;
		}
		finally
		{
			// close cursor
			if (cursor != null)
			{
				cursor.close();
			}
			// close db
			db.close();
		}
	}
}